﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.Server;
using System.Threading;

namespace PSE.Deployment.TeamFoundation.Communication
{
    public class TeamGroup : CommunicationBase
    {
        #region Singleton
        private static TeamGroup instance;
        protected TeamGroup() 
        {
            Communication.VersionControl.Instance.TraceEvent += (sender, e) => RaiseEventTrace(e);
            Communication.TeamServer.Instance.TraceEvent += (sender, e) => RaiseEventTrace(e);
        }
        public static TeamGroup Instance
        {
            get
            {
                if (instance == null)
                {
                    Mutex mutex = new Mutex();
                    mutex.WaitOne();

                    if (instance == null)
                        instance = new TeamGroup();

                    mutex.Close();
                }
                return instance;
            }
        }
        #endregion Singleton

        public List<Entity.TeamGroup> GetTeamGroups(Entity.TeamProject teamProject)
        {
            if (teamProject == null)
                throw new ArgumentNullException("teamProject");

            RaiseEventTrace(string.Format("Obtendo os TeamGroups do TeamProject {0}", teamProject.Name));

            List<Entity.TeamGroup> teamGroups = new List<Entity.TeamGroup>();

            TeamFoundationServer tfs = TeamServer.Instance.GetSinacorTeamServer();
            IGroupSecurityService gss = (IGroupSecurityService)tfs.GetService(typeof(IGroupSecurityService));

            foreach (Identity i in gss.ListApplicationGroups(teamProject.Uri))
            {
                Entity.TeamGroup tg = new Entity.TeamGroup();
                tg.Description = i.Description;
                tg.DisplayName = i.DisplayName;
                tg.Sid = i.Sid;

                tg.TeamProject.Name = teamProject.Name;
                tg.TeamProject.ServerItem = teamProject.ServerItem;
                tg.TeamProject.Uri = teamProject.Uri;

                RaiseEventTrace(string.Format("Adicionando TeamGroup {0}", tg.DisplayName));
                teamGroups.Add(tg);
            }

            teamGroups.Sort();
            return teamGroups;
        }


        public List<Entity.TeamGroup> GetTeamGroups(string userName)
        {
            if(string.IsNullOrEmpty(userName))
                throw new ArgumentNullException("userName");

            RaiseEventTrace(string.Format("Obtendo os TeamGroups pelo Username {0}", userName));

            List<Entity.TeamGroup> teamGroups = new List<Entity.TeamGroup>();

            TeamFoundationServer tfs = TeamServer.Instance.GetSinacorTeamServer();
            IGroupSecurityService gss = (IGroupSecurityService)tfs.GetService(typeof(IGroupSecurityService));

            Identity userIdentity = gss.ReadIdentity(SearchFactor.AccountName, userName, QueryMembership.Direct);

            foreach (string sid in userIdentity.MemberOf)
            {
                Identity groupIdentity = gss.ReadIdentity(SearchFactor.Sid, sid, QueryMembership.Expanded);

                if (teamGroups.Find(t => t.DisplayName == groupIdentity.DisplayName) == null)
                {
                    Entity.TeamGroup tg = new Entity.TeamGroup();
                    tg.Description = "";
                    tg.DisplayName = groupIdentity.DisplayName;
                    tg.Sid = "";

                    RaiseEventTrace(string.Format("Adicionando TeamGroup {0}", tg.DisplayName));
                    teamGroups.Add(tg);
                }
            }

            return teamGroups;
        }

        public List<Entity.TeamGroup> GetTeamGroupsDescription()
        {
            RaiseEventTrace("Obtendo as Descrições de TemGroups");

            List<Entity.TeamGroup> teamGroups = new List<Entity.TeamGroup>();

            TeamFoundationServer tfs = TeamServer.Instance.GetSinacorTeamServer();
            ICommonStructureService css = (ICommonStructureService)tfs.GetService(typeof(ICommonStructureService));
            IGroupSecurityService gss = (IGroupSecurityService)tfs.GetService(typeof(IGroupSecurityService));

            foreach (ProjectInfo pi in css.ListAllProjects())
            {
                foreach (Identity i in gss.ListApplicationGroups(pi.Uri))
                {
                    Entity.TeamGroup tg = new Entity.TeamGroup();
                    tg.Description = i.Description;
                    tg.DisplayName = i.DisplayName;
                    tg.Sid = i.Sid;

                    if (teamGroups.Find(t => t.DisplayName == i.DisplayName) == null)
                    {
                        RaiseEventTrace(string.Format("Adicionando TeamGroup {0}", tg.DisplayName));
                        teamGroups.Add(tg);
                    }
                }
            }

            teamGroups.Sort();
            return teamGroups;
        }
    }
}
